package com.zjp.attendance.server;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.lang.Console;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.zjp.attendance.http.HttpRequestData;
import com.zjp.attendance.constants.CmdConstants;
import com.zjp.attendance.domain.UserInfo;
import com.zjp.attendance.domain.cmd.RealTimeGLogCmd;
import com.zjp.attendance.domain.cmd.ReceiveCmd;
import com.zjp.attendance.enums.CmdCode;
import com.zjp.attendance.service.CmdService;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http.*;
import io.netty.util.CharsetUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

@Slf4j
public class NettyServerHandler extends ChannelInboundHandlerAdapter {
    /**
     * 发送的返回值
     *
     * @param ctx     返回
     * @param context 消息
     * @param status  状态
     */
    private void send(ChannelHandlerContext ctx, String context, HttpResponseStatus status) {
        FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_0, status,
                Unpooled.copiedBuffer(StrUtil.nullToDefault(context, StrUtil.EMPTY_JSON),
                        CharsetUtil.UTF_8));
        send(ctx, response);
    }

    private void send(ChannelHandlerContext ctx, FullHttpResponse response) {
        response.headers().set(HttpHeaderNames.CONTENT_TYPE, HttpHeaderValues.APPLICATION_JSON);
        // 409600
        response.headers().set(CmdConstants.CONTENT_LENGTH, response.content().readableBytes());
        logInfo(response);
        ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
    }

    public <T> HttpRequestData<T> header(FullHttpRequest request) {
        HttpRequestData<T> data = new HttpRequestData<>();
        HttpHeaders headers = request.headers();
        data.setDevId(headers.get("dev-id"));
        data.setTransId(headers.get("trans-id"));
        data.setToken(headers.get("token"));
        data.setDevModel(headers.get("dev-model"));
        data.setCmdReturnCode(headers.get("cmd_return_code"));
        data.setRequestCode(headers.get("request-code"));
        return data;

    }

    public <T> HttpRequestData<T> data(FullHttpRequest request, Class<T> tClass) {
        String body = request.content().toString(CharsetUtil.UTF_8);
        HttpRequestData<T> data = header(request);
        data.setData(JSONUtil.toBean(body, tClass, false));
        return data;
    }


    public void logInfo(FullHttpRequest httpRequest) {
        String uri = httpRequest.uri();
        String methodName = httpRequest.method().name();
        HttpVersion httpVersion = httpRequest.protocolVersion();
        String protocolName = httpVersion.protocolName();
        String body = httpRequest.content().toString(CharsetUtil.UTF_8);
        HttpHeaders headers = httpRequest.headers();
        Iterator<Map.Entry<String, String>> entryIterator = headers.iteratorAsString();
        Console.log("--------------------Base--------------------------");
        Console.log("date == {}", DateUtil.now());
        Console.log("uri == {}", uri);
        Console.log("method == {}", methodName);
        Console.log("protocolName == {}", protocolName);

        Console.log("--------------------headers-----------------------");
        while (entryIterator.hasNext()) {
            Map.Entry<String, String> next = entryIterator.next();
            Console.log("{} == {}", next.getKey(), next.getValue());
        }

        Console.log("----------------------Body------------------------");
        Console.log("body == {}", body);
    }

    static AtomicInteger atomicInteger = new AtomicInteger(0);
    public void logInfo(FullHttpResponse httpResponse) {
        HttpHeaders headers = httpResponse.headers();
        Iterator<Map.Entry<String, String>> entryIterator = headers.iteratorAsString();
        Console.log("--------------------headers-----------------------{}",atomicInteger.incrementAndGet());
        while (entryIterator.hasNext()) {
            Map.Entry<String, String> next = entryIterator.next();
            Console.log("{} == {}", next.getKey(), next.getValue());
        }

    }


    static CmdService cmdService = new CmdService();

    public String getRequestCode(FullHttpRequest httpRequest) {
        return httpRequest.headers().get("request-code");
    }


    /**
     * 读取客户端发送的数据
     *
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        FullHttpRequest httpRequest = (FullHttpRequest) msg;
        logInfo(httpRequest);
        try {
            String request_code = getRequestCode(httpRequest);
            if (request_code.equals(CmdCode.RECEIVE_CMD.getCode())) {
                HttpRequestData<ReceiveCmd> data = data(httpRequest, ReceiveCmd.class);
                send(ctx, cmdService.errorNoCmd());
            } else if (request_code.equals(CmdCode.REALTIME_G_LOG.getCode())) {
                HttpRequestData<RealTimeGLogCmd> data = data(httpRequest, RealTimeGLogCmd.class);
                send(ctx, cmdService.responseTrans(data.getTransId()));
            } else if (request_code.equals(CmdCode.REALTIME_ENROLL_DATA.getCode())) {
                HttpRequestData<UserInfo> data = data(httpRequest, UserInfo.class);
                send(ctx, cmdService.responseTrans(data.getTransId()));
            } else {
                send(ctx, cmdService.errorNoCmd());
            }
        } catch (Exception e) {
            log.error("处理请求失败 {}", e.getMessage());
        } finally {
            //释放请求
            httpRequest.release();
        }
    }


    /**
     * 通道激活
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("客户端的地址： " + ctx.channel().remoteAddress());
    }


    /**
     * 处理异常，一般需要关闭通道
     *
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        System.out.println(ExceptionUtil.getSimpleMessage(cause));
        ctx.close();
    }


}
